﻿//
// SMS PocketPC Proxy by Roberto Freato
// http://www.codeplex.com/SMSPPP/
// http://www.robertofreato.com/
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so. subject to
// the following conditions:
// 
// 1. The above copyright notice and this permission notice shall be
//    included in all copies or substantial portions of the Software.
// 2. Namespaces or Class names of the Software components shall not
//    be modified.
// 3. Neither the name of the copyright holders nor the names of its
//    contributors may be used to endorse or promote products derived from
//    this software without specific prior written permission.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml.Serialization;
using OCDStudio.SMSPPP.Common.Mobile;

namespace OCDStudio.SMSPPP.Common
{
    /// <remarks>
    /// Factory class capable to get a singleton of a connection. It provides method to retrieve 
    /// and set UserConnectionProperties in the local user settings.
    /// </remarks>
    public class MobileConnectionFactory
    {

        private static MobileConnection connection;

        /// <summary>
        /// Factory method to retrieve the connection singleton
        /// </summary>
        /// <returns>A MobileConnection based on the default UsetConnectionProperties</returns>
        /// <see cref="MobileConnectionProperties"/>
        /// <see cref="GetUserConnectionProperties()"/>
        /// <seealso cref="ShowUserSettings"/>
        public static MobileConnection GetInstance()
        {
            return GetInstance(GetUserConnectionProperties());
        }

        /// <summary>
        /// Factory method to retrieve the connection singleton, specifing the properties set.
        /// </summary>
        /// <returns>A MobileConnection based on the specified UsetConnectionProperties</returns>
        /// <see cref="MobileConnectionProperties"/>
        /// <see cref="GetUserConnectionProperties()"/>
        /// <seealso cref="ShowUserSettings"/>
        public static MobileConnection GetInstance(MobileConnectionProperties properties) {
            if (connection == null)
                connection = new MobileConnection(properties);

            connection.Properties = properties;
            return connection;            
        }

        /// <summary>
        /// It clears the stored settings. Useful in case of corrupted settings of program fault.
        /// </summary>
        public static void ClearUserProperties() {
            global::OCDStudio.SMSPPP.Common.Properties.Settings.Default.UserConnectionProperties = "";
            global::OCDStudio.SMSPPP.Common.Properties.Settings.Default.Save();
        }

        /// <summary>
        /// This method provides us with the local User stored settings. It performs a search in the local user
        /// settings folder and create the corresponding object that can be passed to the factory method.
        /// </summary>
        /// <returns>The properties object</returns>
        /// <exception cref="InvalidUserConnectionPropertiesException">
        /// Raised if, for some reason, the stored properties are corrupted or invalid. 
        /// In that case you can use the ClearUserProperties() method to reset to factory defaults.
        /// </exception>
        /// <exception cref="EmptyUserConnectionPropertiesException">
        /// Raised if the settings are stored correctly but are empty.
        /// </exception>
        /// <seealso cref="ClearUserProperties()"/>
        public static MobileConnectionProperties GetUserConnectionProperties() {
            string props = global::OCDStudio.SMSPPP.Common.Properties.Settings.Default.UserConnectionProperties;
            if (!String.IsNullOrEmpty(props))
            {
                XmlSerializer s = new XmlSerializer(typeof(MobileConnectionProperties));
                MobileConnectionProperties properties=null;
                TextReader r = new StringReader(props);
                try
                {
                    properties = (MobileConnectionProperties)s.Deserialize(r);
                }
                catch
                {
                    throw new InvalidUserConnectionPropertiesException();
                }
                r.Close();
                return properties;
            }
            else
            {
                throw new EmptyUserConnectionPropertiesException();
            }
        }

        /// <summary>
        /// It saves the connection settings information in the local user store.
        /// It serializes the properties object in XML format to be used later.
        /// </summary>
        /// <param name="props">The properties object</param>
        public static void SetUserConnectionProperties(MobileConnectionProperties props) {
            XmlSerializer s = new XmlSerializer(typeof(MobileConnectionProperties));
            MemoryStream str = new MemoryStream();
            s.Serialize(str, props);
            str.Seek(0, SeekOrigin.Begin);

            StreamReader reader = new StreamReader(str);
            global::OCDStudio.SMSPPP.Common.Properties.Settings.Default.UserConnectionProperties = reader.ReadToEnd();
            global::OCDStudio.SMSPPP.Common.Properties.Settings.Default.Save();
            
            str.Close();

        }

        /*
        public static void ShowUserConnectionPropertiesDialog(bool modal) {
            if (modal) new ShowUserSettings().ShowDialog();
            else new ShowUserSettings().Show();
            
        }
        */



    }


    
    /// <remarks>
    /// Raised if some method find the settings stored correct but empty.
    /// </remarks>
    public class EmptyUserConnectionPropertiesException : Exception
    {

        public override string Message
        {
            get
            {
                return "Your connection properties are empty. Please try again when they are filled with data.";
            }
        }

    }

    
}
